PlateauPython開発
Plateauデータを使って市街モデルを作る【Plateau】【Python】
2024.11.12
2024.06.14
こんにちは。IU BIM STUDIOの原田です。
Archicadでモデルを作る際にテンプレートを利用しますが、BIMソフトの設定はとにかく数が多いため、テンプレートのどの部分を変えたかを管理することはなかなか難しいです。
更新の前の状態を残しておかないと何が変わったかわからないし、何でそう変えたのかも忘れてしまっている…
そういう問題への対処方法の一つとして、テキストファイルとgitで管理する方法があると思いますので試してみたいと思います。
gitとは、ソフトウェア開発でよく使われるバージョン管理ソフトです。
基本的にはテキストファイルを管理することができ、
管理対象のファイルを前の状態に戻したり、別バージョンを同時に管理したりすることができます。
今回はビルディングマテリアルの設定をマークダウンファイルに書き出してみたいと思います。
マークダウンファイルというのは文章を見やすくするための記法を使ったテキストファイルで、対応しているアプリを使うと整形して表示してくれます。ブログなどを書いたことがある方は使ったことがあるかもしれません。
https://ja.wikipedia.org/wiki/Markdown
実際、マークダウンを使うのがベストかはわかりませんが、管理方法を決めるときには
・作りやすさ
・非エンジニアユーザーにとってのわかりやすさ
・データの視認性
などを考えて選ぶ必要があるかなと思います。
とりあえず今回はマークダウンでやってみたいと思います。
最終的に欲しいのはビルディングマテリアルの情報ですが、ビルディングマテリアルで使われている塗りつぶしと材質の情報はPython APIからビルディングマテリアルを取得した場合、GUIDでしか取得できません。
GUIDを見ても人間にはわからないので、塗りつぶしと材質の情報を先に取得してGUIDから名前を検索できる辞書を作っておきます。
def create_fill_dict() -> dict:
attributes = acc.GetAttributesByType("Fill")
fills = acc.GetFillAttributes(attributes)
fill_dict = {}
for fill in fills:
guid = str(fill.fillAttribute.attributeId.guid)
name = fill.fillAttribute.name
fill_dict[guid] = name
return fill_dict
def create_surface_dict() -> dict:
attributes = acc.GetAttributesByType("Surface")
surfaces = acc.GetSurfaceAttributes(attributes)
surface_dict = {}
for surface in surfaces:
guid = str(surface.surfaceAttribute.attributeId.guid)
name = surface.surfaceAttribute.name
surface_dict[guid] = name
return surface_dict
次にpandasを使って取得した情報を整理します。
pandasはデータ分析などによく使われるpythonのライブラリですが、特に必須ではありません。
# ビルディングマテリアル設定をDataFrameに変換
def builing_material_to_df(fill_dict: dict, surface_dict: dict) -> pd.DataFrame:
# ビルディングマテリアルのIDを取得
attributes = acc.GetAttributesByType("BuildingMaterial")
building_materials = acc.GetBuildingMaterialAttributes(attributes)
# 各ビルディングマテリアルの設定を取得
settings = []
for building_material in building_materials:
attribute_data = building_material.buildingMaterialAttribute
name = attribute_data.name
guid = str(attribute_data.attributeId.guid)
id = attribute_data.id
priority = attribute_data.connectionPriority
cut_fill_id = str(attribute_data.cutFillId.attributeId.guid)
cut_fill = fill_dict[cut_fill_id]
cut_fill_pen = attribute_data.cutFillPenIndex
cut_surface_id = str(attribute_data.cutSurfaceId.attributeId.guid)
cut_surface = surface_dict[cut_surface_id]
settings.append([name, guid, id, priority, cut_fill, cut_fill_pen, cut_surface])
df = pd.DataFrame(
settings,
columns=[
"名前",
"GUID",
"ID",
"優先度",
"切断塗りつぶし",
"切断塗りつぶし前景ペン",
"材質",
],
)
return df
基本的には各ビルディングマテリアルの設定をリストに入れていくだけですが、「切断塗りつぶし」と「材質」はGUIDをキーにして名前をリストに入れます。
そして途中で気づいたのですが、切断塗りつぶし背景ペンはAPIから取得できないようです…
Python APIで取得できない設定はちょいちょいあるので、この辺りは改善してほしいところです。
dataframeを作成したら格納したデータをマークダウン形式に変換します
def row_to_table(data: list) -> str:
# マークダウン記法を適用"|"で各列を区切る
text = "|"
for item in data:
text += str(item)
text += "|"
text += "\n"
return text
def header_to_table(header: list) -> list[str]:
"""マークダウン記法のヘッダを記入
list = ["a","b","c"]
|a|b|c|
|----|----|----|
"""
text_content = []
text_content.append(row_to_table(header))
text = "|"
for _ in range(len(header)):
text += "----|"
text += "\n"
text_content.append(text)
return text_content
# dfをマークダウン記法のテキストに変換
def df_to_text(df: pd.DataFrame) -> list[str]:
text_content = []
text_content.extend(header_to_table(df.columns.values))
for row in df.iterrows():
text_content.append(row_to_table(row[1].values))
return text_content
マークダウンの表形式で設定を書き出していきます。
マークダウンで表を作るには各列の間を|(バーティカルバー)で区切る必要があります。
また、見出し行も欲しいので、それらを書き出すための関数を作成します。
pythonスクリプトを実行すると下記のようなテキストが作成されました。
情報はきちんと出ているようですが、このままでは少し見にくいのでVSCodeの拡張機能を使ってみると、下記のように整えられた状態で見ることができます。
今回使った拡張機能は下記のものです。
https://marketplace.visualstudio.com/items?itemName=searKing.preview-vscode
ブラウザでも拡張機能を使えば、見た目を整えることが可能です。
これで、マークダウンの書き出しは完了です。
次回、gitを使ったファイル管理にトライしてみようと思います。
最後までお読みいただきありがとうございました。
以下にコード全文を載せておきます。
import pandas as pd
from archicad import ACConnection
conn = ACConnection.connect()
acc = conn.commands
act = conn.types
acu = conn.utilities
def create_fill_dict() -> dict:
attributes = acc.GetAttributesByType("Fill")
fills = acc.GetFillAttributes(attributes)
fill_dict = {}
for fill in fills:
guid = str(fill.fillAttribute.attributeId.guid)
name = fill.fillAttribute.name
fill_dict[guid] = name
return fill_dict
def create_surface_dict() -> dict:
attributes = acc.GetAttributesByType("Surface")
surfaces = acc.GetSurfaceAttributes(attributes)
surface_dict = {}
for surface in surfaces:
guid = str(surface.surfaceAttribute.attributeId.guid)
name = surface.surfaceAttribute.name
surface_dict[guid] = name
return surface_dict
# ビルディングマテリアル設定をDataFrameに変換
def builing_material_to_df(fill_dict: dict, surface_dict: dict) -> pd.DataFrame:
# ビルディングマテリアルのIDを取得
attributes = acc.GetAttributesByType("BuildingMaterial")
building_materials = acc.GetBuildingMaterialAttributes(attributes)
# 各ビルディングマテリアルの設定を取得
settings = []
for building_material in building_materials:
attribute_data = building_material.buildingMaterialAttribute
name = attribute_data.name
guid = str(attribute_data.attributeId.guid)
id = attribute_data.id
priority = attribute_data.connectionPriority
cut_fill_id = str(attribute_data.cutFillId.attributeId.guid)
cut_fill = fill_dict[cut_fill_id]
cut_fill_pen = attribute_data.cutFillPenIndex
cut_surface_id = str(attribute_data.cutSurfaceId.attributeId.guid)
cut_surface = surface_dict[cut_surface_id]
settings.append([name, guid, id, priority, cut_fill, cut_fill_pen, cut_surface])
df = pd.DataFrame(
settings,
columns=[
"名前",
"GUID",
"ID",
"優先度",
"切断塗りつぶし",
"切断塗りつぶし前景ペン",
"材質",
],
)
return df
def row_to_table(data: list) -> str:
# マークダウン記法を適用"|"で各列を区切る
text = "|"
for item in data:
text += str(item)
text += "|"
text += "\n"
return text
def header_to_table(header: list) -> list[str]:
"""マークダウン記法のヘッダを記入
list = ["a","b","c"]
|a|b|c|
|----|----|----|
"""
text_content = []
text_content.append(row_to_table(header))
text = "|"
for _ in range(len(header)):
text += "----|"
text += "\n"
text_content.append(text)
return text_content
# dfをマークダウン記法のテキストに変換
def df_to_md(df: pd.DataFrame) -> list[str]:
text_content = []
text_content.extend(header_to_table(df.columns.values))
for row in df.iterrows():
text_content.append(row_to_table(row[1].values))
return text_content
# mdファイルを保存
def save_text_as_md(text_content: list[str], file_name: str) -> None:
with open(file_name, "w", encoding="utf-8") as f:
f.writelines(text_content)
def main():
fill_dict = create_fill_dict()
surface_dict = create_surface_dict()
df = builing_material_to_df(fill_dict, surface_dict)
text = df_to_md(df)
save_text_as_md(text, "building_material.md")
if __name__ == "__main__":
main()
PlateauPython開発
2024.11.12
BIMGISPython開発
2024.10.21
GISPython開発
2024.09.30
GISPython開発
2024.09.03
ARCHICADBIM
2024.08.01
ARCHICADBIM
2024.07.04